## 9.5. Printing

The `lpr` command prints a document on Linux. You might not always invoke this command directly--you may just press a Print button on some glitzy drag-and-drop graphical interface--but ultimately, printing is handled by `lpr` and the other print-management utilities we'll describe here.

If you want to print a program listing, you might enter:

>     lpr myprogram.c

Input is also often piped to `lpr` from another command, as we will see later. `lpr` starts the printing process by storing the data temporarily to a directory called a print spool. Other parts of the print management system, which we showed you how to set up in the section "Section 8.4, "Managing Print Services"" in Chapter 8, "Other Administrative Tasks", remove files from the print queue in the correct order, process the file for printing, and control the flow of data to the printer.

There is at least one print spool for each printer on the system.[40] By default, `lpr` looks for a printer named `lp`. But if you need to specify a printer of a different name, just include a -P option.

> [40]A printer that can be used in different modes of operation, such as for printing faxes as well as letters, may have a separate print spool for each purpose.

For example, to send your document to a printer named `nene`, enter:

>     lpr -Pnene myprogram.c

If you forget the name of a printer, you can look at the names of the spool directories under the /var/spool/lpd directory or at the /etc/printcap file entries to see all the names recognized for each printer.

If you want to use a particular printer for most of your printing needs, you can also set it in the PRINTER environment variable. So, assuming that you are using the `bash` shell, you could make `nene` your personal default printer by putting this command in your .bashrc file:

>     export PRINTER=nene

The -P option in `lpr` overrides the PRINTER variable.

Once you know how to print a file, the next problem you might face is finding out what is happening if your file doesn't instantly print as you expect. You can find out the status of files in the print queue by using the `lpq` command. To find out the status of files sent to your default printer (the PRINTER environment variable applies to all the commands discussed in this section), enter:

>     $ lpq
>     nene is ready and printing
>     Rank   Owner      Job  Files                                 Total Size
>     active lovelace   020  (standard input)                     776708 bytes
>     1st    parcifal   024  (standard input)                    2297842 bytes
>     1st    lark       023  (standard input)                      10411 bytes

You see that the printer is running, but there are large jobs queued ahead of yours (if you are lark). If you just can't wait, you might decide to remove the job from the print queue. You can use the job number of the printing task that `lpq` reported to remove the printing job:

>     $ lprm 23
>     023 dequeued
>     023 dequeued

The spooled print file identified as job 023 is discarded, along with an associated file that contains instructions for formatting the file.

You can narrow the `lpq` report by asking about a specific print job by task ID (rarely used), by printer, or by user ID. For example, to get a report that identifies spooled files sent to a printer named `ada` you would enter:

>     $ lpq ada
>     ada is ready and printing
>     Rank   Owner      Job  Files                                 Total Size
>     active lovelace   788  standard input                        16713 bytes
>     1st    lark       796  standard input                        70750 bytes

If you are the root user, you can kill all pending printing tasks by entering the command:

>     lprm -

If you are not the root user, issuing that command kills only the printing tasks you own. This restriction also holds true if you specify a printer:

>     lprm ada

If you are root, the `ada` print queue is emptied. If you are a normal user, only the print files you own are removed from the specified print spool. The `lprm` utility reports on the tasks it kills.

The root user can kill all the print tasks issued by any user, by specifying:

>     lprm username

If you issue `lprm` with no argument, it deletes the currently active print jobs that you own. This is equivalent to entering:

>     lprm yourusername

If you want to see whether a printer is down, you can use the `lpc` command:

>     /usr/sbin/lpc status ada

See the section "Section 8.4.12, "Controlling Printer Services with lpc"" in Chapter 8, "Other Administrative Tasks" for details. The `lpc` utility is usually installed in the /sbin or /usr/sbin directory.

Now for some more examples of common printing tasks and filters you can use.

To get a quick hardcopy printout of the printcap manual page, enter:

>     man printcap | col -b | lpr

The `man` command finds, formats, and outputs the printcap manual page in an enriched ASCII output that uses backspaces to overstrike and underline characters (in place of italics) for highlighting. The output is piped through `col`, a Unix text filter, where `-b` specifies stripping the "backspace" instructions embedded in the man page which results in simple text strings, still maintaining the layout of the formatted man page. The output of `col` is piped to `lpr`, which spools the text in a spool directory.

If you want to simulate underlining, you could instead use a filter designed originally for formatting print to a text display:

>     man printcap | colcrt | lpr

Suppose you want to print the fully enriched man page with highlighting and all. You might use a command like this:

>     groff -man -Tps /usr/man/man5/printcap.5 | lpr

The `groff` command applies the `man` macros to the file specified, creating PostScript output (specified by -Tps); output is passed to `lpr`, which spools it, and `lpd` applies the default print-processing instructions from the /etc/printcap file.

Most Linux installations use BSD-style print utilities developed for the Berkeley Software Distribution of Unix. If you find utilities named `lp`, `lpstat`, `cancel`, and `lpadmin`, your Linux host has a System V-based print system. You need to read the manual pages and perhaps other documentation for that package. There are other printing systems that could be installed on your system, such as the PLP package, but we only document the usual Linux BSD-based print-management utilities here. We also describe how to use some of the other commonly installed print support utilities for Linux, such as filters that prepare documents in special ways to print on your printers.

The BSD-style print-management system is traditionally called "lp" after the line printers that were the standard print devices of the era in which the package was developed.[41] In the Linux community, the BSD print management package is more commonly usually called "the lpr package." Of course, the `lpr` command is only one tool in the package.

> [41]Don't be misled if you hear someone use the term `lp`, which is a confusing misnomer. There is no `lp` utility in the BSD print-management package, but there is one in the later-developed System V print package. It is still possible that your BSD package allows you to use an `lp` command in order to print, though. Some systems use a shell script (filter) named `lp` to convert `lp` command options into `lpr` command options, and pass them on to `lpr`. This is solely for the convenience of users that are familiar with the System V `lp` command.

### 9.5.1. What Happens to a File After It's Put on the Queue

Only the root user has the ability to access printers directly, without using the printing system. (That's not a wise thing to do, by the way.) Linux doesn't grant system users the ability to address various physical devices directly, because crippling conflicts could result, and also because it's just too much work for them to bother with. Instead, utilities call background system processes to schedule your printing among other tasks, convert source file data to print to a specific printer using its printer language and protocols, set print resolution and format the pages, and add (or know not to add) header and footer data and page numbering. Linux configures itself to handle its physical devices when it is booted, including setting up ports and protocols to handle printing.

The print-management system is controlled by `lpd`, the "line printer daemon," which has necessary privileges to access printers for you. Once the print management system is installed, `lpd` is started every time the Linux system is initialized (booted). The /etc/printcap file provides the control information `lpd` needs to manage the files you print.

Here's what the printer-management system is actually doing when you enter a printing command. When called, `lpr` checks whether you have a PRINTER environment variable set. If you do, `lpr` loads the print options stored there as instructions to process the print file it is receiving. Next, `lpr` applies any option parameters you gave it or that are passed to it by a program that preprocessed the file. Last, `lpr` sends the file to the spool directory for the printer that will be used, along with another temporary file that stores the processing specifications for `lpd` to apply. Then `lpr` notifies `lpd` that there is a print file spooled. If `lpr` receives an option it doesn't understand, it passes the option on to the print filter, which we'll discuss shortly.

When `lpd` finds a job in the print spool, it reads the processing specifications (which tell it how to pass the print file through filters and direct the output to a device) and completes the printing task, erasing the print file and processing file when the printer has received all of the processed print file.

All Unix printing systems process a file through at least one filter to prepare it for output. This filter processes the file using any of the usual options that Unix print utilities pass to it.

Appropriate filters are set up by the administrator and specified in the printcap file to meet your usual printing needs. If you want to do any special processing, you give your processing instructions as options to the print commands. Your instructions enter the printer management system through the `lpr` command (directly on the command line or passed indirectly by some other command). The `lpr` command spools the print file in the correct print spool directory and stores the related processing instructions in an associated file in the same print spool.

When it is time to print your file, the `lpd` daemon reads any special processing directions for the print file, which may override default processing directions set in the /etc/printcap file. When `lpd` passes your file to the correct filter for the printer you are using, it also passes along any instructions it did not act on. The filter then further processes the file itself according to the instructions or calls yet other filters to perform the processing it could not. The file is then passed on to the printer by `lpd`. You can see that this hidden filter provides most actual control of print formatting.

If you have special printing requirements, you need to learn the options to pass to the filter that control print formatting. The standard options are discussed in the `lpr` manual page. Additional filter options are documented in the filter package that is used. Later we discuss a couple of filters that are probably on your system. We can't possibly describe how to use all the filters and filter packages available to you for use with Linux. You should read the manual pages for the filters on your system to learn how to get the output you want.

A well-configured printcap file uses the printer's name to determine what kind of filtering to apply. For example, if your printer can automatically format and print an HTML (World Wide Web) document, you may be able to tell `lpr` to print to the `html` printer:

>     lpr -Phtml ~/homepage.html

This printer could actually be the same printer you use for PostScript, for example, but by specifying a printer named `html` you cause `lpd` to use a different printcap definition that processes the file through an HTML filter into a graphic format the printer understands.

Since the system administrator controls the contents of /etc/printcap, you are not at liberty to simply exchange one filtering process for another. You do have a lot of control on the command line and through environment variables that affect your typesetting tools, filter parameters, and printer selection. When necessary, you can filter files before submitting them to the printer management system. For example, if you receive email with an attached graphic that you cannot display or print, you might save the file to disk and then use one of the many graphic conversion utilities available for Linux to convert it (filter it) into a printable form, before passing the file to `lpr`.

Much depends on the cleverness of the filter. If an option is passed through `lpr` and the filter but is never interpreted, it may end up passed through to the printer, either before or after the actual print file. This may have no effect. In some cases, a printer configuration command is deliberately passed to the printer this way. More typically a passed option prints extra pages, probably with stray characters on them; usually this is harmless. If you observe such behavior, make sure you aren't causing the problem yourself with environment variables, badly formed commands, or unsupported options. If it wasn't your fault, the administrator should try to trace the problem to save paper and time.

Some filters automatically apply the PRINTER environment variable if you set it. You should know that the equivalent printer variable for a System V print system is LPDEST, and some print filters you acquire may expect or accept that variable. You may even work on a mixed network with accounts on different systems where one uses BSD print management and another uses System V. If you are a belt-and-suspenders kind of person, you can set both LPDEST and PRINTER in your shell initialization file.

Problems using a print filter may affect other users on a multiuser system. Report any difficulties to the print-system administrator.

### 9.5.2. nenscript

The `nenscript` utility is a flexible filter that provides good formatted output for PostScript printers, even from ASCII text files. It isn't a basic Linux utility, but it is included in a number of Linux distributions and can be retrieved from the usual Linux FTP sites. While you can invoke `nenscript` to send a prepared file to the printer, it usually is specified in the /etc/printcap file as a pass-through filter that takes text from the standard input and sends it to the standard output.

Suppose you are printing out a C program and want line numbering and a printout on green-striped fanfold paper (not the same format you'd want when printing those graphics you downloaded from the Internet on your nifty PostScript printer). You need to have the program processed, and then insert the line numbers in front of the lines. The solution is to process the file through a filter such as the `nenscript` utility (if you have it installed). After doing its own processing, `nenscript` passes the file to `lpr` for spooling and printing to your trusty tractor-feed printer (named `dino` here):

>     nenscript -B -L66 -N -Pdino myprogram.c

The `nenscript` filter numbers each line of the file passed through it when you specify the -N option. The -B option suppresses the usual header information from being printed on each page, and the -L66 option specifies formatting at 66 lines per page. The `nenscript` filter just passes the -Pdino option through to `lpr`, which interprets it and directs the output to `dino`'s print spool directory for printing.

When called on the command line, `nenscript` automatically passes output to `lpr` unless you specify standard output by supplying the -p option. You don't need to pipe or redirect `nenscript` output to `lpr` explicitly.[42]

> [42]The `nenscript` utility could also be the usual filter that the printcap file specifies for use with your printer. It won't hurt for the file to go through a properly designed filter more than once. A filter passes a processing instruction on only when it does not perform the processing itself. As a filter executes an instruction, it discards the processing option. You needn't worry that your file will end up with two sets of line numbers on the page.

Suppose you are going to print a lot of program listings today. For convenience, you can set an environment variable for `nenscript` to specially process and print your listings each time:

>     export NENSCRIPT=" -B -L66 -N -Pdino"

Now, to print your listing correctly, all you need enter is:

>     nenscript myprogram.c

`nenscript` optionally sends output to a file, which is often useful for preparing PostScript files on Linux hosts that don't actually have a PostScript printer available. For example, to convert a text file to a PostScript file, formatted for two-column printing on A4 pages in 6-point Courier font, for instance, you would type:

>     nenscript -2 -fCourier6 -TA4 -pdocument.ps document.txt

The -2 option overrides the one-column default, and the -fCourier6 option overrides the 7-point Courier default for two-column output. (The one-column default is Courier10; `nenscript` always uses Courier font when converting plain text into PostScript.) The -TA4 argument specifies European standard A4 paper format. If `nenscript` was compiled using the US_VERSION variable, the default paper format is 8.5 x 11 inches (if you're not using the US_VERSION environment variable, you can specify this size through -TUS). The -p option specifies that the output should be stored to document.ps, and the filename specified with no option is the input to `nenscript`. If no filename had been specified, `nenscript` would have taken standard input as the filename.

As another example, to print the `nenscript` manual page as basic text on a PostScript printer, enter:

>     man nenscript | col -b | nenscript

The `man` command retrieves and formats the manual page and formats it for text display. The `col -b` command strips the backspace instructions for highlighting and underlining, leaving plain text that is piped to the `nenscript` filter. This turns the plain text into simple PostScript with some "pretty printing" that applies headers, footers, page numbering, and the like. Finally, the file is passed to `lpr`, which spools the file. The file passes once more through the filter specified in the printcap file, which could be a "dummy" filter that simply passes the text through. Or the filter could do additional things, such as attaching a formfeed character to the end of the print file.

If you specify the -Z option with `nenscript`, it attempts to detect PostScript files passed to it and passes them through unaltered.

If a PostScript file is passed to `nenscript` and is taken for a text file (probably because `nenscript` was not called with the `-Z` option) `nenscript` will encapsulate it and pass it through to print. This can result in the PostScript code being printed out literally. Even a small PostScript file can use up a lot of paper in this way.

Suppose the `lpd` daemon already applies `nenscript` to process files sent to the printer. The file should still process correctly if it does, but intervening filtering could cause the second pass through `nenscript` to encapsulate the PostScript source. It would be safer to set the NENSCRIPT variable. When the `nenscript` filter is applied by /etc/printcap to a print file, the options set in your NENSCRIPT environment variable are used, but are overridden by explicit options passed through `lpr` from a command line or another utility.

Note that you could specify the default printer to use either in PRINTER or as a `-P` argument stored to NENSCRIPT. If you set NENSCRIPT to specify a printer to use, that printer will be used every time NENSCRIPT filters one of your files. We recommend that you set PRINTER rather than `-P` in NENSCRIPT, so that you can change the printer specification and have it filtered appropriately.

Copyright © 2001 O'Reilly & Associates. All rights reserved.